package com.grom.util;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import com.grom.util.Constants;
import com.grom.exception.DocumentParseException;
import com.grom.exception.NoSuchColumnDefinationException;
import com.grom.exception.NodeProppertyLostException;

public abstract class ColumnConfig {

	private static final String CONFIG_FILENAME = Constants.COLUMN_CONFIG_FILE_NAME;

	private static XmlReader reader = new XmlReader(CONFIG_FILENAME);
	/**
	 * all the defination of the column is stored here
	 */
	private static Map<Integer, String> container = reader.getAllDefination();

	public static Map<Integer, String> getColumnDefine() {
		return container;
	}

	/**
	 * 
	 * @param pos
	 * @return
	 */
	public static String getPropName(Integer pos) {
		String tmp = getColumnDefine().get(pos);
		if (tmp == null || tmp.trim().length() == 0) {
			throw new NoSuchColumnDefinationException(pos);
		}
		return tmp;
	}

	/**
	 * if the column name not defined in the column-config.xml<br>
	 * return -1
	 * 
	 * @return
	 */
	public static Integer getPositionByPropName(String propertyName) {
		Set<Entry<Integer, String>> entrys = getColumnDefine().entrySet();
		for (Entry<Integer, String> entry : entrys) {
			if (entry.getValue().equals(propertyName)) {
				return entry.getKey();
			}
		}
		return Constants.NONCOLUMN_DEFINATION;
	}

	public static void main(String[] args) {
		System.out.println(new XmlReader(Constants.COLUMN_CONFIG_FILE_NAME).getAllDefination());
	}
}

class XmlReader {
	static DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

	Document document = null;

	XmlReader(String fileName) {
		try {
			DocumentBuilder builder = factory.newDocumentBuilder();
			document = builder.parse(XmlReader.class.getClassLoader().getResourceAsStream(fileName));
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
			throw new DocumentParseException(fileName, e);
		} catch (SAXException e) {
			e.printStackTrace();
			throw new DocumentParseException(fileName, e);
		} catch (IOException e) {
			e.printStackTrace();
			throw new DocumentParseException(fileName, e);
		}
	}

	/**
	 * get all the defination in the config file
	 * 
	 * @return
	 */
	Map<Integer, String> getAllDefination() {
		Map<Integer, String> tmp = new HashMap<Integer, String>();
		Element root = document.getDocumentElement();
		NodeList nodeList = root.getElementsByTagName(Constants.COLUMN_BASIC_KEY);
		int length = nodeList.getLength();
		for (int i = 0; i < length; i++) {
			Node node = nodeList.item(i);
			if (node == null) {
				continue;
			}
			Integer key = getColumnIndexFromItem(node);
			String value = getPropNameFromItem(node);
			if (key == null || value == null) {
				throw new NodeProppertyLostException(node.getTextContent());
			}
			tmp.put(key, value);
		}
		return tmp;
	}

	/**
	 * 
	 * @param node
	 *            which is a column-item node
	 * @return
	 */
	@SuppressWarnings("unused")
	private String getColumnNameFromItem(Node node) {
		NodeList lists = node.getChildNodes();
		for (int i = 0; i < lists.getLength(); i++) {
			Node tmp = lists.item(i);
			if (tmp == null) {
				continue;
			}
			if (tmp.getNodeName().equalsIgnoreCase(Constants.COLUMN_NAME_KEY)) {
				return tmp.getTextContent().trim();
			}
		}
		return null;
	}

	/**
	 * 
	 * @param node
	 *            which is a column-item node
	 * @return
	 */
	private String getPropNameFromItem(Node node) {
		NodeList lists = node.getChildNodes();
		for (int i = 0; i < lists.getLength(); i++) {
			Node tmp = lists.item(i);
			if (tmp == null) {
				continue;
			}
			if (tmp.getNodeName().equalsIgnoreCase(Constants.PROPERTY_NAME_KEY)) {
				return tmp.getTextContent().trim();
			}
		}
		return null;
	}

	/**
	 * 
	 * @param node
	 *            which is a column-item node
	 * @return
	 */
	private Integer getColumnIndexFromItem(Node node) {
		NodeList lists = node.getChildNodes();
		for (int i = 0; i < lists.getLength(); i++) {
			Node tmp = lists.item(i);
			if (tmp == null) {
				continue;
			}
			if (tmp.getNodeName().equalsIgnoreCase(Constants.COLUMN_POSITION_KEY)) {
				return Constants.CHAR_TO_NUM.get(tmp.getTextContent().trim().toUpperCase());
			}
		}
		return null;
	}
}